package com.union.vehicleassistant.module.main;

import android.app.Activity;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattService;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.viewpager.widget.ViewPager;

import com.blankj.utilcode.util.ArrayUtils;
import com.blankj.utilcode.util.BusUtils;
import com.blankj.utilcode.util.LogUtils;
import com.clj.fastble.BleManager;
import com.clj.fastble.data.BleDevice;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.union.vehicleassistant.R;
import com.union.vehicleassistant.action.DialogAction;
import com.union.vehicleassistant.adapter.FixedFragmentPagerAdapter;
import com.union.vehicleassistant.app.AppActivity;
import com.union.vehicleassistant.bean.ChannelBean;
import com.union.vehicleassistant.common.Constant;
import com.union.vehicleassistant.manager.ActivityManager;
import com.union.vehicleassistant.module.service.BindBleService;
import com.union.vehicleassistant.module.setting.BluetoothActivity;
import com.union.vehicleassistant.module.setting.SettingActivity;
import com.union.vehicleassistant.other.DoubleClickHelper;
import com.union.vehicleassistant.util.BlueToothUtil;
import com.union.vehicleassistant.util.DarkModeUtils;
import com.union.vehicleassistant.util.MagicIndicatorUtils;
import com.union.vehicleassistant.util.RxTimer;
import com.union.vehicleassistant.util.SettingUtils;
import com.union.vehicleassistant.util.SimpleBlueToothStateChangeListener;
import com.union.vehicleassistant.util.UnitManager;
import com.union.vehicleassistant.widget.ArcSeekBar;

import net.lucode.hackware.magicindicator.MagicIndicator;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 首页容器
 */
public class MainActivity extends AppActivity implements DialogAction {

    private static final String INTENT_KEY_IN_FRAGMENT_INDEX = "fragmentIndex";
    public static final String KEY_CODE_APPLY_MODE = "KEY_CODE_APPLY_MODE";
    private MagicIndicator indicator;
    private ArcSeekBar boardViewOne;
    private ArcSeekBar boardViewTwo;
    private TextView tvProgressOne;
    private TextView tvProgressTwo;
    private TextView tvPressureTwo;
    private TextView tvPressureOne;
    private ViewPager vpMode;
    private List<ChannelBean> channels = new ArrayList<>();
    private int defModePosition = -1; // 记录上次使用的模式
    private FixedFragmentPagerAdapter pagerAdapter;
    private BleDevice connectDevice = null; // 已连接的设备
    private RxTimer timer;
    private boolean isConnected;// 标记是否已经链接蓝牙
    private boolean useBar; // 使用bar作为单位
    private String unit;
    private boolean serviceBondState = false; // 服务绑定状态
    private BindBleService.BleBinder bleBinder;

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            bleBinder = (BindBleService.BleBinder) iBinder;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };


    public static void start(Context context) {
        Intent intent = new Intent(context, MainActivity.class);
        if (!(context instanceof Activity)) {
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        }
        context.startActivity(intent);
    }

    @Override
    protected int getLayoutId() {
        return R.layout.activity_main;
    }

    @Override
    protected void initView() {
        indicator = findViewById(R.id.magic_indicator);
        boardViewOne = findViewById(R.id.arcSeekBarOne);
        boardViewTwo = findViewById(R.id.arcSeekBarTwo);
        tvProgressOne = findViewById(R.id.tv_setting_one);
        tvProgressTwo = findViewById(R.id.tv_setting_two);
        tvPressureOne = findViewById(R.id.tv_pressure_one);
        tvPressureTwo = findViewById(R.id.tv_pressure_two);
        vpMode = findViewById(R.id.vp_mode);

        unit = SettingUtils.getInstance().getPressureUnit();
        tvPressureOne.setText(unit + "\n0");
        tvPressureTwo.setText(unit + "\n0");

        setListener();

        initMode();

//        setDefaultMode();
    }

    private void setListener() {
        vpMode.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);
                BusUtils.post(Constant.BUS_MODE_CHANGE);
            }
        });

        boardViewOne.setOnChangeListener(new ArcSeekBar.OnChangeListener() {

            @Override
            public void onProgressChanged(double progress, double max, boolean fromUser) {
                tvProgressOne.setText(UnitManager.getSuitPressure(progress, false));
            }

            @Override
            public void onStopTrackingTouch(boolean isCanDrag) {
                if (isCanDrag && isConnected) {
                    double progress = boardViewOne.getProgress();
                    changeChannelData(progress, true);
                }
            }
        });

        boardViewTwo.setOnChangeListener(new ArcSeekBar.OnChangeListener() {

            @Override
            public void onProgressChanged(double progress, double max, boolean fromUser) {
                tvProgressTwo.setText(UnitManager.getSuitPressure(progress, false));
            }

            @Override
            public void onStopTrackingTouch(boolean isCanDrag) {
                if (isCanDrag && isConnected) {
                    double progress = boardViewTwo.getProgress();
                    changeChannelData(progress, false);
                }
            }
        });
    }

    /**
     * <p>初始化模式；模式分别对应不同的预设值{@link ChannelBean}</p>
     */
    private void initMode() {
        String preSettingData = SettingUtils.getInstance().getPreSettingData();
        channels = new Gson().fromJson(preSettingData, new TypeToken<List<ChannelBean>>() {
        }.getType());

        List<Fragment> fragments = new ArrayList<>();
        for (int i = 0; i < channels.size(); i++) {
            ChannelBean bean = channels.get(i);
            if (bean.isDefaultMode()) {
                defModePosition = i;
            }
            fragments.add(ModeFragment.newInstance(new Gson().toJson(bean), i));
        }

        if (null == pagerAdapter) {
            pagerAdapter = new FixedFragmentPagerAdapter(getSupportFragmentManager());
            vpMode.setAdapter(pagerAdapter);
        }
        pagerAdapter.setFragmentList(fragments);
        MagicIndicatorUtils.onlyIndicator(getContext(), indicator, vpMode, fragments.size());
    }

    /**
     * 设置默认模式（上次使用的模式）
     */
    private void setDefaultMode() {
        int currentMode = Math.max(defModePosition, 0);

        for (int i = 0; i < channels.size(); i++) {
            ChannelBean channel = channels.get(i);
            channel.setDefaultMode(currentMode == i);
        }

        ChannelBean bean = channels.get(currentMode);
        // 保存默认数据 没有默认数据就使用第一个
        SettingUtils.getInstance().setDefaultMode(bean);
        SettingUtils.getInstance().setPreSettingData(channels);
        // 切换到默认模式的页面
        LogUtils.d("setCurrentItem-》", currentMode);
        vpMode.setCurrentItem(currentMode);
        BusUtils.post(Constant.BUS_MODE_CHANGE);
        changeModeCode(bean);
    }

    @Override
    protected void initData() {
        onNewIntent(getIntent());

        bindService();
    }

    /**
     * 绑定服务
     */
    private void bindService() {
        Intent intent = new Intent(this, BindBleService.class);
        serviceBondState = bindService(intent, connection, BIND_AUTO_CREATE);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
    }

    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        // 保存当前 Fragment 索引位置
        int fragmentPos = 0;//获取当前fragment的位置
        outState.putInt(INTENT_KEY_IN_FRAGMENT_INDEX, fragmentPos);
    }

    @Override
    protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        // 恢复当前 Fragment 索引位置
        int tabPos = savedInstanceState.getInt(INTENT_KEY_IN_FRAGMENT_INDEX);
        switchFragment(tabPos);
    }

    private void switchFragment(int fragmentIndex) {
        vpMode.setCurrentItem(fragmentIndex);
    }

    @Override
    public void onRightClick(View view) {
        super.onRightClick(view);
        startActivity(SettingActivity.class);
    }

    @Override
    public void onLeftClick(View view) {
        startActivity(BluetoothActivity.class);
    }

    @Override
    protected boolean isStatusBarDarkFont() {
        return !DarkModeUtils.isDarkMode(getContext());
    }

    @Override
    public void onBackPressed() {
        if (!DoubleClickHelper.isOnDoubleClick()) {
            toast(R.string.home_exit_hint);
            return;
        }

        // 移动到上一个任务栈，避免侧滑引起的不良反应
        moveTaskToBack(false);
        postDelayed(() -> {
            // 进行内存优化，销毁掉所有的界面
            ActivityManager.getInstance().finishAllActivities();
            // 销毁进程（注意：调用此 API 可能导致当前 Activity onDestroy 方法无法正常回调）
            // System.exit(0);
        }, 300);
    }

    @Override
    protected void onResume() {
        super.onResume();
        BusUtils.register(this);
        unit = SettingUtils.getInstance().getPressureUnit();
        checkAlreadyBindBle();
    }

    /**
     * 检查是否链接过蓝牙
     */
    private void checkAlreadyBindBle() {
        if (isConnected) {
            return;
        }
        startConnectBle();
        String mac = SettingUtils.getInstance().getConnectBluetoothMac();
        if (TextUtils.isEmpty(mac)) {

        } else {
            boolean connected = BleManager.getInstance().isConnected(mac);
            setLeftTitle(connected ? R.string.ble_state_connected : R.string.ble_state_unconnected);
            if (connected) return;
            // 已链接过蓝，可以进行相关操作
            startConnectBle();
        }
    }

    /**
     * 开启服务链接蓝牙
     */
    private void startConnectBle() {
        if (null != bleBinder) {
            bleBinder.connectBle();
        }
    }

    @Override
    protected void onDestroy() {
        unbindService(connection);
        serviceBondState = false;
        BusUtils.unregister(this);
        super.onDestroy();
    }

    /**
     * 切换模式事件通知
     *
     * @param bean 模式信息
     */
    @BusUtils.Bus(tag = KEY_CODE_APPLY_MODE)
    public void onChangeMode(ChannelBean bean) {
        SettingUtils.getInstance().setDefaultMode(bean);
        changeModeCode(bean);
    }

    /**
     * <p>
     * 切换/设置模式指令<br/>
     * 用于设置默认模式和切换模式两种场景
     * </p>
     *
     * @param bean 模式
     */
    private void changeModeCode(ChannelBean bean) {
        // 设置模式；先取消定时任务，然后发送写数据指令，然后开启定时器发送读数据指令
        if (null != timer) {
            timer.cancel();
        }
        boardViewOne.setProgress(bean.getChannelOne());
        boardViewTwo.setProgress(bean.getChannelTwo());
        if (!isConnected) {
            toast(R.string.ble_disconnect);
            return;
        }

        sendWriteDataCode(bean);
        postDelayed(this::sendReadDataCode, 333);
    }

    @BusUtils.Bus(tag = Constant.BUS_KEY_BLE_FAIL)
    public void onBleConnectFail() {
        connectDevice = null;
        isConnected = false;
        setLeftTitle(R.string.ble_state_unconnected);
        messageDialog(getContext(), R.string.ble_connect_fail, () -> startActivity(BluetoothActivity.class));
    }

    @BusUtils.Bus(tag = Constant.BUS_KEY_BLE_SUCCESS)
    public void onBleConnect(BleDevice bleDevice) {
        connectDevice = bleDevice;
        isConnected = true;
        setLeftTitle(R.string.ble_state_connected);
        postDelayed(() -> {
            readData();
            sendReadDataCode();
        }, 200);
    }

    @BusUtils.Bus(tag = Constant.BUS_KEY_BLE_DISCONNECT)
    public void onBleDisConnect() {
        connectDevice = null;
        isConnected = false;
        setLeftTitle(R.string.ble_state_unconnected);
        messageDialog(getContext(), R.string.ble_disconnect, true, null);
    }

    @BusUtils.Bus(tag = Constant.BUS_KEY_BLE_NO_BLE)
    public void onWithOutBleConfig() {
        connectDevice = null;
        isConnected = false;
        setLeftTitle(R.string.ble_state_unconnected);
        messageDialog(getContext(), R.string.ble_unconnected_to_setting, () -> startActivity(BluetoothActivity.class));
    }

    /**
     * 切换单位通知
     */
    @BusUtils.Bus(tag = Constant.BUS_UNIT_CHANGE)
    public void onUnitChange() {
        tvProgressOne.setText(UnitManager.getSuitPressure(boardViewOne.getProgress(), false));
        tvProgressTwo.setText(UnitManager.getSuitPressure(boardViewTwo.getProgress(), false));
        String unit = SettingUtils.getInstance().getPressureUnit();
        tvPressureOne.setText(unit + "\n0");
        tvPressureTwo.setText(unit + "\n0");
    }

    /**
     * 链接蓝牙设备通知
     */
    @BusUtils.Bus(tag = Constant.BUS_CONNECT_BLUETOOTH)
    public void onNeedConnectBle() {
        if (null != bleBinder) {
            bleBinder.connectBle();
        }
    }


    /**
     * 初次链接设备，给设备发送指令来激活设备下发数据
     */
    private void sendReadDataCode() {
        if (timer == null) {
            timer = new RxTimer();
        }
        timer.interval(333, times -> {
            if (null != connectDevice) {
                BluetoothGatt gatt = BleManager.getInstance().getBluetoothGatt(connectDevice);
                BlueToothUtil.writeData(connectDevice, gatt, Constant.BLE_DEVICE_READ_DATA_LEFT_CODE);
                postDelayed(() -> BlueToothUtil.writeData(connectDevice, gatt, Constant.BLE_DEVICE_READ_DATA_RIGHT_CODE), 100);
            }
        });
    }

    /**
     * 发送写数据指令
     * byte[] writeLeftCode = {0x02, 0x06, 0x00, 0x01, 0x0000, (byte) 0xD8, 0x0A};// 修改左通道数据指令
     * byte[] writeRightCode = {0x02, 0x06, 0x00, 0x02, 0x0000, (byte) 0xD8, 0x0A};// 修改右通道数据指令
     *
     * @param channel 通道
     */
    private void sendWriteDataCode(ChannelBean channel) {
        int channelOne = channel.getChannelOne();
        int channelTwo = channel.getChannelTwo();
        changeChannelData(channelOne, true);
        postDelayed(() -> changeChannelData(channelTwo, false), 200);
    }

    /**
     * 切换通道压力
     *
     * @param pressure 压力值
     * @param left     是否左通道
     */
    private void changeChannelData(double pressure, boolean left) {
        if (null == connectDevice) return;
        ByteBuffer leftByteBuffer = ByteBuffer.allocate(8);
        leftByteBuffer.put((byte) 2);
        leftByteBuffer.put((byte) 6);
        leftByteBuffer.putShort((short) (left ? 1 : 2));
        leftByteBuffer.putShort((short) (pressure * 100));
        leftByteBuffer.put((byte) 0xD8);
        leftByteBuffer.put((byte) 0x0A);
        BluetoothGatt gatt = BleManager.getInstance().getBluetoothGatt(connectDevice);
        BlueToothUtil.writeData(connectDevice, gatt, leftByteBuffer.array());
    }

    /**
     * 读取蓝牙发送的数据
     */
    private void readData() {
        BlueToothUtil.registerReceiveCallback(connectDevice, new SimpleBlueToothStateChangeListener() {
            @Override
            public void onOpenNotify(BluetoothGattService service, String uuidNotify) {
                super.onOpenNotify(service, uuidNotify);
            }

            @Override
            public void onReceiveCharacter(byte[] receivedData) {
                super.onReceiveCharacter(receivedData);
                LogUtils.d("获取到的数据：", receivedData, receivedData.length);
                byte[] flagData = ArrayUtils.subArray(receivedData, 2, 4);
                ByteBuffer buffer = ByteBuffer.wrap(Objects.requireNonNull(flagData));
                short aShort = buffer.getShort();

                byte[] dataValue = ArrayUtils.subArray(receivedData, 5, 7);
                ByteBuffer dataBuffer = ByteBuffer.wrap(Objects.requireNonNull(dataValue));
                short dataShort = dataBuffer.getShort();
                double showValue = UnitManager.getDoublePressure(dataShort / 100.0);
                String unit = SettingUtils.getInstance().getPressureUnit();
                if (aShort == 1) {
                    tvPressureOne.setText(unit + "\n" + showValue);
                } else if (aShort == 2) {
                    tvPressureTwo.setText(unit + "\n" + showValue);
                }
            }
        });
    }
}